package com.liuqi.knet.rpc.exchange;

import com.liuqi.knet.remoting.Channel;
import com.liuqi.knet.remoting.ChannelHandler;
import com.liuqi.knet.remoting.RemotingException;
import com.liuqi.knet.remoting.exchange.Request;
import com.liuqi.knet.remoting.exchange.Response;
import com.liuqi.knet.remoting.exchange.support.DefaultResponseFuture;
import com.liuqi.knet.remoting.transport.AbstractChannelHandlerDelegate;
import com.liuqi.knet.rpc.Invocation;
import com.liuqi.knet.rpc.Invoker;
import com.liuqi.knet.util.CommonUtil;

/**
 * @author liuqi
 * @date 2025/3/6 15:20
 **/
public class ExchangeHandler extends AbstractChannelHandlerDelegate {

    private final Invoker invoker;

    public ExchangeHandler(ChannelHandler handler, Invoker invoker) {
        super(handler);
        if (handler == null) {
            throw new IllegalArgumentException("handler == null");
        }
        if (invoker == null) {
            throw new IllegalArgumentException("invoker == null");
        }
        this.invoker = invoker;
    }

    @Override
    public void received(Channel channel, Object message) throws RemotingException {
        if (message instanceof Request) {
            Request request = (Request) message;
            if (request.isTwoWay()) {
                Response response = handleRequest(channel, request);
                channel.send(response);     // 响应
            } else {
                reply(channel, request.getData());
            }
        } else if (message instanceof Response) {
            handleResponse(channel, (Response) message);
        } else {
            handler.received(channel, message);
        }
    }

    /**
     * invoker
     *
     * @param channel
     * @param message
     * @return
     * @throws RemotingException
     */
    Object reply(Channel channel, Object message) throws RemotingException {
        if (message instanceof Invocation) {
            return invoker.invoke((Invocation) message);
        }
        throw new RemotingException("不支持的请求: "
                + (message == null ? null : (message.getClass().getName() + ": " + message))
                + ", 通道: 远程地址: " + channel.getRemoteAddress() + " --> 本地地址: " + channel.getLocalAddress());
    }

    Response handleRequest(Channel channel, Request request) throws RemotingException {
        Response resp = new Response(request.getId());
        try {
            Object result = reply(channel, request.getData());
            resp.setState(Response.OK);
            resp.setResult(result);
        } catch (Throwable e) {
            resp.setState(Response.SERVICE_ERROR);
            resp.setErrorMessage(CommonUtil.toString(e));
        }
        return resp;
    }

    void handleResponse(Channel channel, Response response) throws RemotingException {
        if (response != null) {
            DefaultResponseFuture.received(response);
        }
    }

}
